#include <stdint.h>
#include <stddef.h>
#include <algorithm>

// #include "Endian.h"
#include "Aes.h"

const uint32_t AES::Te0[256] = {
	0xC66363A5U, 0xF87C7C84U, 0xEE777799U, 0xF67B7B8DU, 0xFFF2F20DU, 0xD66B6BBDU, 0xDE6F6FB1U, 0x91C5C554U,
	0x60303050U, 0x02010103U, 0xCE6767A9U, 0x562B2B7DU, 0xE7FEFE19U, 0xB5D7D762U, 0x4DABABE6U, 0xEC76769AU,
	0x8FCACA45U, 0x1F82829DU, 0x89C9C940U, 0xFA7D7D87U, 0xEFFAFA15U, 0xB25959EBU, 0x8E4747C9U, 0xFBF0F00BU,
	0x41ADADECU, 0xB3D4D467U, 0x5FA2A2FDU, 0x45AFAFEAU, 0x239C9CBFU, 0x53A4A4F7U, 0xE4727296U, 0x9BC0C05BU,
	0x75B7B7C2U, 0xE1FDFD1CU, 0x3D9393AEU, 0x4C26266AU, 0x6C36365AU, 0x7E3F3F41U, 0xF5F7F702U, 0x83CCCC4FU,
	0x6834345CU, 0x51A5A5F4U, 0xD1E5E534U, 0xF9F1F108U, 0xE2717193U, 0xABD8D873U, 0x62313153U, 0x2A15153FU,
	0x0804040CU, 0x95C7C752U, 0x46232365U, 0x9DC3C35EU, 0x30181828U, 0x379696A1U, 0x0A05050FU, 0x2F9A9AB5U,
	0x0E070709U, 0x24121236U, 0x1B80809BU, 0xDFE2E23DU, 0xCDEBEB26U, 0x4E272769U, 0x7FB2B2CDU, 0xEA75759FU,
	0x1209091BU, 0x1D83839EU, 0x582C2C74U, 0x341A1A2EU, 0x361B1B2DU, 0xDC6E6EB2U, 0xB45A5AEEU, 0x5BA0A0FBU,
	0xA45252F6U, 0x763B3B4DU, 0xB7D6D661U, 0x7DB3B3CEU, 0x5229297BU, 0xDDE3E33EU, 0x5E2F2F71U, 0x13848497U,
	0xA65353F5U, 0xB9D1D168U, 0x00000000U, 0xC1EDED2CU, 0x40202060U, 0xE3FCFC1FU, 0x79B1B1C8U, 0xB65B5BEDU,
	0xD46A6ABEU, 0x8DCBCB46U, 0x67BEBED9U, 0x7239394BU, 0x944A4ADEU, 0x984C4CD4U, 0xB05858E8U, 0x85CFCF4AU,
	0xBBD0D06BU, 0xC5EFEF2AU, 0x4FAAAAE5U, 0xEDFBFB16U, 0x864343C5U, 0x9A4D4DD7U, 0x66333355U, 0x11858594U,
	0x8A4545CFU, 0xE9F9F910U, 0x04020206U, 0xFE7F7F81U, 0xA05050F0U, 0x783C3C44U, 0x259F9FBAU, 0x4BA8A8E3U,
	0xA25151F3U, 0x5DA3A3FEU, 0x804040C0U, 0x058F8F8AU, 0x3F9292ADU, 0x219D9DBCU, 0x70383848U, 0xF1F5F504U,
	0x63BCBCDFU, 0x77B6B6C1U, 0xAFDADA75U, 0x42212163U, 0x20101030U, 0xE5FFFF1AU, 0xFDF3F30EU, 0xBFD2D26DU,
	0x81CDCD4CU, 0x180C0C14U, 0x26131335U, 0xC3ECEC2FU, 0xBE5F5FE1U, 0x359797A2U, 0x884444CCU, 0x2E171739U,
	0x93C4C457U, 0x55A7A7F2U, 0xFC7E7E82U, 0x7A3D3D47U, 0xC86464ACU, 0xBA5D5DE7U, 0x3219192BU, 0xE6737395U,
	0xC06060A0U, 0x19818198U, 0x9E4F4FD1U, 0xA3DCDC7FU, 0x44222266U, 0x542A2A7EU, 0x3B9090ABU, 0x0B888883U,
	0x8C4646CAU, 0xC7EEEE29U, 0x6BB8B8D3U, 0x2814143CU, 0xA7DEDE79U, 0xBC5E5EE2U, 0x160B0B1DU, 0xADDBDB76U,
	0xDBE0E03BU, 0x64323256U, 0x743A3A4EU, 0x140A0A1EU, 0x924949DBU, 0x0C06060AU, 0x4824246CU, 0xB85C5CE4U,
	0x9FC2C25DU, 0xBDD3D36EU, 0x43ACACEFU, 0xC46262A6U, 0x399191A8U, 0x319595A4U, 0xD3E4E437U, 0xF279798BU,
	0xD5E7E732U, 0x8BC8C843U, 0x6E373759U, 0xDA6D6DB7U, 0x018D8D8CU, 0xB1D5D564U, 0x9C4E4ED2U, 0x49A9A9E0U,
	0xD86C6CB4U, 0xAC5656FAU, 0xF3F4F407U, 0xCFEAEA25U, 0xCA6565AFU, 0xF47A7A8EU, 0x47AEAEE9U, 0x10080818U,
	0x6FBABAD5U, 0xF0787888U, 0x4A25256FU, 0x5C2E2E72U, 0x381C1C24U, 0x57A6A6F1U, 0x73B4B4C7U, 0x97C6C651U,
	0xCBE8E823U, 0xA1DDDD7CU, 0xE874749CU, 0x3E1F1F21U, 0x964B4BDDU, 0x61BDBDDCU, 0x0D8B8B86U, 0x0F8A8A85U,
	0xE0707090U, 0x7C3E3E42U, 0x71B5B5C4U, 0xCC6666AAU, 0x904848D8U, 0x06030305U, 0xF7F6F601U, 0x1C0E0E12U,
	0xC26161A3U, 0x6A35355FU, 0xAE5757F9U, 0x69B9B9D0U, 0x17868691U, 0x99C1C158U, 0x3A1D1D27U, 0x279E9EB9U,
	0xD9E1E138U, 0xEBF8F813U, 0x2B9898B3U, 0x22111133U, 0xD26969BBU, 0xA9D9D970U, 0x078E8E89U, 0x339494A7U,
	0x2D9B9BB6U, 0x3C1E1E22U, 0x15878792U, 0xC9E9E920U, 0x87CECE49U, 0xAA5555FFU, 0x50282878U, 0xA5DFDF7AU,
	0x038C8C8FU, 0x59A1A1F8U, 0x09898980U, 0x1A0D0D17U, 0x65BFBFDAU, 0xD7E6E631U, 0x844242C6U, 0xD06868B8U,
	0x824141C3U, 0x299999B0U, 0x5A2D2D77U, 0x1E0F0F11U, 0x7BB0B0CBU, 0xA85454FCU, 0x6DBBBBD6U, 0x2C16163AU
};

const uint32_t AES::Te1[256] = {
	0xA5C66363U, 0x84F87C7CU, 0x99EE7777U, 0x8DF67B7BU, 0x0DFFF2F2U, 0xBDD66B6BU, 0xB1DE6F6FU, 0x5491C5C5U,
	0x50603030U, 0x03020101U, 0xA9CE6767U, 0x7D562B2BU, 0x19E7FEFEU, 0x62B5D7D7U, 0xE64DABABU, 0x9AEC7676U,
	0x458FCACAU, 0x9D1F8282U, 0x4089C9C9U, 0x87FA7D7DU, 0x15EFFAFAU, 0xEBB25959U, 0xC98E4747U, 0x0BFBF0F0U,
	0xEC41ADADU, 0x67B3D4D4U, 0xFD5FA2A2U, 0xEA45AFAFU, 0xBF239C9CU, 0xF753A4A4U, 0x96E47272U, 0x5B9BC0C0U,
	0xC275B7B7U, 0x1CE1FDFDU, 0xAE3D9393U, 0x6A4C2626U, 0x5A6C3636U, 0x417E3F3FU, 0x02F5F7F7U, 0x4F83CCCCU,
	0x5C683434U, 0xF451A5A5U, 0x34D1E5E5U, 0x08F9F1F1U, 0x93E27171U, 0x73ABD8D8U, 0x53623131U, 0x3F2A1515U,
	0x0C080404U, 0x5295C7C7U, 0x65462323U, 0x5E9DC3C3U, 0x28301818U, 0xA1379696U, 0x0F0A0505U, 0xB52F9A9AU,
	0x090E0707U, 0x36241212U, 0x9B1B8080U, 0x3DDFE2E2U, 0x26CDEBEBU, 0x694E2727U, 0xCD7FB2B2U, 0x9FEA7575U,
	0x1B120909U, 0x9E1D8383U, 0x74582C2CU, 0x2E341A1AU, 0x2D361B1BU, 0xB2DC6E6EU, 0xEEB45A5AU, 0xFB5BA0A0U,
	0xF6A45252U, 0x4D763B3BU, 0x61B7D6D6U, 0xCE7DB3B3U, 0x7B522929U, 0x3EDDE3E3U, 0x715E2F2FU, 0x97138484U,
	0xF5A65353U, 0x68B9D1D1U, 0x00000000U, 0x2CC1EDEDU, 0x60402020U, 0x1FE3FCFCU, 0xC879B1B1U, 0xEDB65B5BU,
	0xBED46A6AU, 0x468DCBCBU, 0xD967BEBEU, 0x4B723939U, 0xDE944A4AU, 0xD4984C4CU, 0xE8B05858U, 0x4A85CFCFU,
	0x6BBBD0D0U, 0x2AC5EFEFU, 0xE54FAAAAU, 0x16EDFBFBU, 0xC5864343U, 0xD79A4D4DU, 0x55663333U, 0x94118585U,
	0xCF8A4545U, 0x10E9F9F9U, 0x06040202U, 0x81FE7F7FU, 0xF0A05050U, 0x44783C3CU, 0xBA259F9FU, 0xE34BA8A8U,
	0xF3A25151U, 0xFE5DA3A3U, 0xC0804040U, 0x8A058F8FU, 0xAD3F9292U, 0xBC219D9DU, 0x48703838U, 0x04F1F5F5U,
	0xDF63BCBCU, 0xC177B6B6U, 0x75AFDADAU, 0x63422121U, 0x30201010U, 0x1AE5FFFFU, 0x0EFDF3F3U, 0x6DBFD2D2U,
	0x4C81CDCDU, 0x14180C0CU, 0x35261313U, 0x2FC3ECECU, 0xE1BE5F5FU, 0xA2359797U, 0xCC884444U, 0x392E1717U,
	0x5793C4C4U, 0xF255A7A7U, 0x82FC7E7EU, 0x477A3D3DU, 0xACC86464U, 0xE7BA5D5DU, 0x2B321919U, 0x95E67373U,
	0xA0C06060U, 0x98198181U, 0xD19E4F4FU, 0x7FA3DCDCU, 0x66442222U, 0x7E542A2AU, 0xAB3B9090U, 0x830B8888U,
	0xCA8C4646U, 0x29C7EEEEU, 0xD36BB8B8U, 0x3C281414U, 0x79A7DEDEU, 0xE2BC5E5EU, 0x1D160B0BU, 0x76ADDBDBU,
	0x3BDBE0E0U, 0x56643232U, 0x4E743A3AU, 0x1E140A0AU, 0xDB924949U, 0x0A0C0606U, 0x6C482424U, 0xE4B85C5CU,
	0x5D9FC2C2U, 0x6EBDD3D3U, 0xEF43ACACU, 0xA6C46262U, 0xA8399191U, 0xA4319595U, 0x37D3E4E4U, 0x8BF27979U,
	0x32D5E7E7U, 0x438BC8C8U, 0x596E3737U, 0xB7DA6D6DU, 0x8C018D8DU, 0x64B1D5D5U, 0xD29C4E4EU, 0xE049A9A9U,
	0xB4D86C6CU, 0xFAAC5656U, 0x07F3F4F4U, 0x25CFEAEAU, 0xAFCA6565U, 0x8EF47A7AU, 0xE947AEAEU, 0x18100808U,
	0xD56FBABAU, 0x88F07878U, 0x6F4A2525U, 0x725C2E2EU, 0x24381C1CU, 0xF157A6A6U, 0xC773B4B4U, 0x5197C6C6U,
	0x23CBE8E8U, 0x7CA1DDDDU, 0x9CE87474U, 0x213E1F1FU, 0xDD964B4BU, 0xDC61BDBDU, 0x860D8B8BU, 0x850F8A8AU,
	0x90E07070U, 0x427C3E3EU, 0xC471B5B5U, 0xAACC6666U, 0xD8904848U, 0x05060303U, 0x01F7F6F6U, 0x121C0E0EU,
	0xA3C26161U, 0x5F6A3535U, 0xF9AE5757U, 0xD069B9B9U, 0x91178686U, 0x5899C1C1U, 0x273A1D1DU, 0xB9279E9EU,
	0x38D9E1E1U, 0x13EBF8F8U, 0xB32B9898U, 0x33221111U, 0xBBD26969U, 0x70A9D9D9U, 0x89078E8EU, 0xA7339494U,
	0xB62D9B9BU, 0x223C1E1EU, 0x92158787U, 0x20C9E9E9U, 0x4987CECEU, 0xFFAA5555U, 0x78502828U, 0x7AA5DFDFU,
	0x8F038C8CU, 0xF859A1A1U, 0x80098989U, 0x171A0D0DU, 0xDA65BFBFU, 0x31D7E6E6U, 0xC6844242U, 0xB8D06868U,
	0xC3824141U, 0xB0299999U, 0x775A2D2DU, 0x111E0F0FU, 0xCB7BB0B0U, 0xFCA85454U, 0xD66DBBBBU, 0x3A2C1616U
};

const uint32_t AES::Te2[256] = {
	0x63A5C663U, 0x7C84F87CU, 0x7799EE77U, 0x7B8DF67BU, 0xF20DFFF2U, 0x6BBDD66BU, 0x6FB1DE6FU, 0xC55491C5U,
	0x30506030U, 0x01030201U, 0x67A9CE67U, 0x2B7D562BU, 0xFE19E7FEU, 0xD762B5D7U, 0xABE64DABU, 0x769AEC76U,
	0xCA458FCAU, 0x829D1F82U, 0xC94089C9U, 0x7D87FA7DU, 0xFA15EFFAU, 0x59EBB259U, 0x47C98E47U, 0xF00BFBF0U,
	0xADEC41ADU, 0xD467B3D4U, 0xA2FD5FA2U, 0xAFEA45AFU, 0x9CBF239CU, 0xA4F753A4U, 0x7296E472U, 0xC05B9BC0U,
	0xB7C275B7U, 0xFD1CE1FDU, 0x93AE3D93U, 0x266A4C26U, 0x365A6C36U, 0x3F417E3FU, 0xF702F5F7U, 0xCC4F83CCU,
	0x345C6834U, 0xA5F451A5U, 0xE534D1E5U, 0xF108F9F1U, 0x7193E271U, 0xD873ABD8U, 0x31536231U, 0x153F2A15U,
	0x040C0804U, 0xC75295C7U, 0x23654623U, 0xC35E9DC3U, 0x18283018U, 0x96A13796U, 0x050F0A05U, 0x9AB52F9AU,
	0x07090E07U, 0x12362412U, 0x809B1B80U, 0xE23DDFE2U, 0xEB26CDEBU, 0x27694E27U, 0xB2CD7FB2U, 0x759FEA75U,
	0x091B1209U, 0x839E1D83U, 0x2C74582CU, 0x1A2E341AU, 0x1B2D361BU, 0x6EB2DC6EU, 0x5AEEB45AU, 0xA0FB5BA0U,
	0x52F6A452U, 0x3B4D763BU, 0xD661B7D6U, 0xB3CE7DB3U, 0x297B5229U, 0xE33EDDE3U, 0x2F715E2FU, 0x84971384U,
	0x53F5A653U, 0xD168B9D1U, 0x00000000U, 0xED2CC1EDU, 0x20604020U, 0xFC1FE3FCU, 0xB1C879B1U, 0x5BEDB65BU,
	0x6ABED46AU, 0xCB468DCBU, 0xBED967BEU, 0x394B7239U, 0x4ADE944AU, 0x4CD4984CU, 0x58E8B058U, 0xCF4A85CFU,
	0xD06BBBD0U, 0xEF2AC5EFU, 0xAAE54FAAU, 0xFB16EDFBU, 0x43C58643U, 0x4DD79A4DU, 0x33556633U, 0x85941185U,
	0x45CF8A45U, 0xF910E9F9U, 0x02060402U, 0x7F81FE7FU, 0x50F0A050U, 0x3C44783CU, 0x9FBA259FU, 0xA8E34BA8U,
	0x51F3A251U, 0xA3FE5DA3U, 0x40C08040U, 0x8F8A058FU, 0x92AD3F92U, 0x9DBC219DU, 0x38487038U, 0xF504F1F5U,
	0xBCDF63BCU, 0xB6C177B6U, 0xDA75AFDAU, 0x21634221U, 0x10302010U, 0xFF1AE5FFU, 0xF30EFDF3U, 0xD26DBFD2U,
	0xCD4C81CDU, 0x0C14180CU, 0x13352613U, 0xEC2FC3ECU, 0x5FE1BE5FU, 0x97A23597U, 0x44CC8844U, 0x17392E17U,
	0xC45793C4U, 0xA7F255A7U, 0x7E82FC7EU, 0x3D477A3DU, 0x64ACC864U, 0x5DE7BA5DU, 0x192B3219U, 0x7395E673U,
	0x60A0C060U, 0x81981981U, 0x4FD19E4FU, 0xDC7FA3DCU, 0x22664422U, 0x2A7E542AU, 0x90AB3B90U, 0x88830B88U,
	0x46CA8C46U, 0xEE29C7EEU, 0xB8D36BB8U, 0x143C2814U, 0xDE79A7DEU, 0x5EE2BC5EU, 0x0B1D160BU, 0xDB76ADDBU,
	0xE03BDBE0U, 0x32566432U, 0x3A4E743AU, 0x0A1E140AU, 0x49DB9249U, 0x060A0C06U, 0x246C4824U, 0x5CE4B85CU,
	0xC25D9FC2U, 0xD36EBDD3U, 0xACEF43ACU, 0x62A6C462U, 0x91A83991U, 0x95A43195U, 0xE437D3E4U, 0x798BF279U,
	0xE732D5E7U, 0xC8438BC8U, 0x37596E37U, 0x6DB7DA6DU, 0x8D8C018DU, 0xD564B1D5U, 0x4ED29C4EU, 0xA9E049A9U,
	0x6CB4D86CU, 0x56FAAC56U, 0xF407F3F4U, 0xEA25CFEAU, 0x65AFCA65U, 0x7A8EF47AU, 0xAEE947AEU, 0x08181008U,
	0xBAD56FBAU, 0x7888F078U, 0x256F4A25U, 0x2E725C2EU, 0x1C24381CU, 0xA6F157A6U, 0xB4C773B4U, 0xC65197C6U,
	0xE823CBE8U, 0xDD7CA1DDU, 0x749CE874U, 0x1F213E1FU, 0x4BDD964BU, 0xBDDC61BDU, 0x8B860D8BU, 0x8A850F8AU,
	0x7090E070U, 0x3E427C3EU, 0xB5C471B5U, 0x66AACC66U, 0x48D89048U, 0x03050603U, 0xF601F7F6U, 0x0E121C0EU,
	0x61A3C261U, 0x355F6A35U, 0x57F9AE57U, 0xB9D069B9U, 0x86911786U, 0xC15899C1U, 0x1D273A1DU, 0x9EB9279EU,
	0xE138D9E1U, 0xF813EBF8U, 0x98B32B98U, 0x11332211U, 0x69BBD269U, 0xD970A9D9U, 0x8E89078EU, 0x94A73394U,
	0x9BB62D9BU, 0x1E223C1EU, 0x87921587U, 0xE920C9E9U, 0xCE4987CEU, 0x55FFAA55U, 0x28785028U, 0xDF7AA5DFU,
	0x8C8F038CU, 0xA1F859A1U, 0x89800989U, 0x0D171A0DU, 0xBFDA65BFU, 0xE631D7E6U, 0x42C68442U, 0x68B8D068U,
	0x41C38241U, 0x99B02999U, 0x2D775A2DU, 0x0F111E0FU, 0xB0CB7BB0U, 0x54FCA854U, 0xBBD66DBBU, 0x163A2C16U
};

const uint32_t AES::Te3[256] = {
	0x6363A5C6U, 0x7C7C84F8U, 0x777799EEU, 0x7B7B8DF6U, 0xF2F20DFFU, 0x6B6BBDD6U, 0x6F6FB1DEU, 0xC5C55491U,
	0x30305060U, 0x01010302U, 0x6767A9CEU, 0x2B2B7D56U, 0xFEFE19E7U, 0xD7D762B5U, 0xABABE64DU, 0x76769AECU,
	0xCACA458FU, 0x82829D1FU, 0xC9C94089U, 0x7D7D87FAU, 0xFAFA15EFU, 0x5959EBB2U, 0x4747C98EU, 0xF0F00BFBU,
	0xADADEC41U, 0xD4D467B3U, 0xA2A2FD5FU, 0xAFAFEA45U, 0x9C9CBF23U, 0xA4A4F753U, 0x727296E4U, 0xC0C05B9BU,
	0xB7B7C275U, 0xFDFD1CE1U, 0x9393AE3DU, 0x26266A4CU, 0x36365A6CU, 0x3F3F417EU, 0xF7F702F5U, 0xCCCC4F83U,
	0x34345C68U, 0xA5A5F451U, 0xE5E534D1U, 0xF1F108F9U, 0x717193E2U, 0xD8D873ABU, 0x31315362U, 0x15153F2AU,
	0x04040C08U, 0xC7C75295U, 0x23236546U, 0xC3C35E9DU, 0x18182830U, 0x9696A137U, 0x05050F0AU, 0x9A9AB52FU,
	0x0707090EU, 0x12123624U, 0x80809B1BU, 0xE2E23DDFU, 0xEBEB26CDU, 0x2727694EU, 0xB2B2CD7FU, 0x75759FEAU,
	0x09091B12U, 0x83839E1DU, 0x2C2C7458U, 0x1A1A2E34U, 0x1B1B2D36U, 0x6E6EB2DCU, 0x5A5AEEB4U, 0xA0A0FB5BU,
	0x5252F6A4U, 0x3B3B4D76U, 0xD6D661B7U, 0xB3B3CE7DU, 0x29297B52U, 0xE3E33EDDU, 0x2F2F715EU, 0x84849713U,
	0x5353F5A6U, 0xD1D168B9U, 0x00000000U, 0xEDED2CC1U, 0x20206040U, 0xFCFC1FE3U, 0xB1B1C879U, 0x5B5BEDB6U,
	0x6A6ABED4U, 0xCBCB468DU, 0xBEBED967U, 0x39394B72U, 0x4A4ADE94U, 0x4C4CD498U, 0x5858E8B0U, 0xCFCF4A85U,
	0xD0D06BBBU, 0xEFEF2AC5U, 0xAAAAE54FU, 0xFBFB16EDU, 0x4343C586U, 0x4D4DD79AU, 0x33335566U, 0x85859411U,
	0x4545CF8AU, 0xF9F910E9U, 0x02020604U, 0x7F7F81FEU, 0x5050F0A0U, 0x3C3C4478U, 0x9F9FBA25U, 0xA8A8E34BU,
	0x5151F3A2U, 0xA3A3FE5DU, 0x4040C080U, 0x8F8F8A05U, 0x9292AD3FU, 0x9D9DBC21U, 0x38384870U, 0xF5F504F1U,
	0xBCBCDF63U, 0xB6B6C177U, 0xDADA75AFU, 0x21216342U, 0x10103020U, 0xFFFF1AE5U, 0xF3F30EFDU, 0xD2D26DBFU,
	0xCDCD4C81U, 0x0C0C1418U, 0x13133526U, 0xECEC2FC3U, 0x5F5FE1BEU, 0x9797A235U, 0x4444CC88U, 0x1717392EU,
	0xC4C45793U, 0xA7A7F255U, 0x7E7E82FCU, 0x3D3D477AU, 0x6464ACC8U, 0x5D5DE7BAU, 0x19192B32U, 0x737395E6U,
	0x6060A0C0U, 0x81819819U, 0x4F4FD19EU, 0xDCDC7FA3U, 0x22226644U, 0x2A2A7E54U, 0x9090AB3BU, 0x8888830BU,
	0x4646CA8CU, 0xEEEE29C7U, 0xB8B8D36BU, 0x14143C28U, 0xDEDE79A7U, 0x5E5EE2BCU, 0x0B0B1D16U, 0xDBDB76ADU,
	0xE0E03BDBU, 0x32325664U, 0x3A3A4E74U, 0x0A0A1E14U, 0x4949DB92U, 0x06060A0CU, 0x24246C48U, 0x5C5CE4B8U,
	0xC2C25D9FU, 0xD3D36EBDU, 0xACACEF43U, 0x6262A6C4U, 0x9191A839U, 0x9595A431U, 0xE4E437D3U, 0x79798BF2U,
	0xE7E732D5U, 0xC8C8438BU, 0x3737596EU, 0x6D6DB7DAU, 0x8D8D8C01U, 0xD5D564B1U, 0x4E4ED29CU, 0xA9A9E049U,
	0x6C6CB4D8U, 0x5656FAACU, 0xF4F407F3U, 0xEAEA25CFU, 0x6565AFCAU, 0x7A7A8EF4U, 0xAEAEE947U, 0x08081810U,
	0xBABAD56FU, 0x787888F0U, 0x25256F4AU, 0x2E2E725CU, 0x1C1C2438U, 0xA6A6F157U, 0xB4B4C773U, 0xC6C65197U,
	0xE8E823CBU, 0xDDDD7CA1U, 0x74749CE8U, 0x1F1F213EU, 0x4B4BDD96U, 0xBDBDDC61U, 0x8B8B860DU, 0x8A8A850FU,
	0x707090E0U, 0x3E3E427CU, 0xB5B5C471U, 0x6666AACCU, 0x4848D890U, 0x03030506U, 0xF6F601F7U, 0x0E0E121CU,
	0x6161A3C2U, 0x35355F6AU, 0x5757F9AEU, 0xB9B9D069U, 0x86869117U, 0xC1C15899U, 0x1D1D273AU, 0x9E9EB927U,
	0xE1E138D9U, 0xF8F813EBU, 0x9898B32BU, 0x11113322U, 0x6969BBD2U, 0xD9D970A9U, 0x8E8E8907U, 0x9494A733U,
	0x9B9BB62DU, 0x1E1E223CU, 0x87879215U, 0xE9E920C9U, 0xCECE4987U, 0x5555FFAAU, 0x28287850U, 0xDFDF7AA5U,
	0x8C8C8F03U, 0xA1A1F859U, 0x89898009U, 0x0D0D171AU, 0xBFBFDA65U, 0xE6E631D7U, 0x4242C684U, 0x6868B8D0U,
	0x4141C382U, 0x9999B029U, 0x2D2D775AU, 0x0F0F111EU, 0xB0B0CB7BU, 0x5454FCA8U, 0xBBBBD66DU, 0x16163A2CU
};

const uint32_t AES::Te4[256] = {
	0x63636363U, 0x7C7C7C7CU, 0x77777777U, 0x7B7B7B7BU, 0xF2F2F2F2U, 0x6B6B6B6BU, 0x6F6F6F6FU, 0xC5C5C5C5U,
	0x30303030U, 0x01010101U, 0x67676767U, 0x2B2B2B2BU, 0xFEFEFEFEU, 0xD7D7D7D7U, 0xABABABABU, 0x76767676U,
	0xCACACACAU, 0x82828282U, 0xC9C9C9C9U, 0x7D7D7D7DU, 0xFAFAFAFAU, 0x59595959U, 0x47474747U, 0xF0F0F0F0U,
	0xADADADADU, 0xD4D4D4D4U, 0xA2A2A2A2U, 0xAFAFAFAFU, 0x9C9C9C9CU, 0xA4A4A4A4U, 0x72727272U, 0xC0C0C0C0U,
	0xB7B7B7B7U, 0xFDFDFDFDU, 0x93939393U, 0x26262626U, 0x36363636U, 0x3F3F3F3FU, 0xF7F7F7F7U, 0xCCCCCCCCU,
	0x34343434U, 0xA5A5A5A5U, 0xE5E5E5E5U, 0xF1F1F1F1U, 0x71717171U, 0xD8D8D8D8U, 0x31313131U, 0x15151515U,
	0x04040404U, 0xC7C7C7C7U, 0x23232323U, 0xC3C3C3C3U, 0x18181818U, 0x96969696U, 0x05050505U, 0x9A9A9A9AU,
	0x07070707U, 0x12121212U, 0x80808080U, 0xE2E2E2E2U, 0xEBEBEBEBU, 0x27272727U, 0xB2B2B2B2U, 0x75757575U,
	0x09090909U, 0x83838383U, 0x2C2C2C2CU, 0x1A1A1A1AU, 0x1B1B1B1BU, 0x6E6E6E6EU, 0x5A5A5A5AU, 0xA0A0A0A0U,
	0x52525252U, 0x3B3B3B3BU, 0xD6D6D6D6U, 0xB3B3B3B3U, 0x29292929U, 0xE3E3E3E3U, 0x2F2F2F2FU, 0x84848484U,
	0x53535353U, 0xD1D1D1D1U, 0x00000000U, 0xEDEDEDEDU, 0x20202020U, 0xFCFCFCFCU, 0xB1B1B1B1U, 0x5B5B5B5BU,
	0x6A6A6A6AU, 0xCBCBCBCBU, 0xBEBEBEBEU, 0x39393939U, 0x4A4A4A4AU, 0x4C4C4C4CU, 0x58585858U, 0xCFCFCFCFU,
	0xD0D0D0D0U, 0xEFEFEFEFU, 0xAAAAAAAAU, 0xFBFBFBFBU, 0x43434343U, 0x4D4D4D4DU, 0x33333333U, 0x85858585U,
	0x45454545U, 0xF9F9F9F9U, 0x02020202U, 0x7F7F7F7FU, 0x50505050U, 0x3C3C3C3CU, 0x9F9F9F9FU, 0xA8A8A8A8U,
	0x51515151U, 0xA3A3A3A3U, 0x40404040U, 0x8F8F8F8FU, 0x92929292U, 0x9D9D9D9DU, 0x38383838U, 0xF5F5F5F5U,
	0xBCBCBCBCU, 0xB6B6B6B6U, 0xDADADADAU, 0x21212121U, 0x10101010U, 0xFFFFFFFFU, 0xF3F3F3F3U, 0xD2D2D2D2U,
	0xCDCDCDCDU, 0x0C0C0C0CU, 0x13131313U, 0xECECECECU, 0x5F5F5F5FU, 0x97979797U, 0x44444444U, 0x17171717U,
	0xC4C4C4C4U, 0xA7A7A7A7U, 0x7E7E7E7EU, 0x3D3D3D3DU, 0x64646464U, 0x5D5D5D5DU, 0x19191919U, 0x73737373U,
	0x60606060U, 0x81818181U, 0x4F4F4F4FU, 0xDCDCDCDCU, 0x22222222U, 0x2A2A2A2AU, 0x90909090U, 0x88888888U,
	0x46464646U, 0xEEEEEEEEU, 0xB8B8B8B8U, 0x14141414U, 0xDEDEDEDEU, 0x5E5E5E5EU, 0x0B0B0B0BU, 0xDBDBDBDBU,
	0xE0E0E0E0U, 0x32323232U, 0x3A3A3A3AU, 0x0A0A0A0AU, 0x49494949U, 0x06060606U, 0x24242424U, 0x5C5C5C5CU,
	0xC2C2C2C2U, 0xD3D3D3D3U, 0xACACACACU, 0x62626262U, 0x91919191U, 0x95959595U, 0xE4E4E4E4U, 0x79797979U,
	0xE7E7E7E7U, 0xC8C8C8C8U, 0x37373737U, 0x6D6D6D6DU, 0x8D8D8D8DU, 0xD5D5D5D5U, 0x4E4E4E4EU, 0xA9A9A9A9U,
	0x6C6C6C6CU, 0x56565656U, 0xF4F4F4F4U, 0xEAEAEAEAU, 0x65656565U, 0x7A7A7A7AU, 0xAEAEAEAEU, 0x08080808U,
	0xBABABABAU, 0x78787878U, 0x25252525U, 0x2E2E2E2EU, 0x1C1C1C1CU, 0xA6A6A6A6U, 0xB4B4B4B4U, 0xC6C6C6C6U,
	0xE8E8E8E8U, 0xDDDDDDDDU, 0x74747474U, 0x1F1F1F1FU, 0x4B4B4B4BU, 0xBDBDBDBDU, 0x8B8B8B8BU, 0x8A8A8A8AU,
	0x70707070U, 0x3E3E3E3EU, 0xB5B5B5B5U, 0x66666666U, 0x48484848U, 0x03030303U, 0xF6F6F6F6U, 0x0E0E0E0EU,
	0x61616161U, 0x35353535U, 0x57575757U, 0xB9B9B9B9U, 0x86868686U, 0xC1C1C1C1U, 0x1D1D1D1DU, 0x9E9E9E9EU,
	0xE1E1E1E1U, 0xF8F8F8F8U, 0x98989898U, 0x11111111U, 0x69696969U, 0xD9D9D9D9U, 0x8E8E8E8EU, 0x94949494U,
	0x9B9B9B9BU, 0x1E1E1E1EU, 0x87878787U, 0xE9E9E9E9U, 0xCECECECEU, 0x55555555U, 0x28282828U, 0xDFDFDFDFU,
	0x8C8C8C8CU, 0xA1A1A1A1U, 0x89898989U, 0x0D0D0D0DU, 0xBFBFBFBFU, 0xE6E6E6E6U, 0x42424242U, 0x68686868U,
	0x41414141U, 0x99999999U, 0x2D2D2D2DU, 0x0F0F0F0FU, 0xB0B0B0B0U, 0x54545454U, 0xBBBBBBBBU, 0x16161616U
};

const uint32_t AES::Td0[256] = {
	0x51F4A750U, 0x7E416553U, 0x1A17A4C3U, 0x3A275E96U, 0x3BAB6BCBU, 0x1F9D45F1U, 0xACFA58ABU, 0x4BE30393U,
	0x2030FA55U, 0xAD766DF6U, 0x88CC7691U, 0xF5024C25U, 0x4FE5D7FCU, 0xC52ACBD7U, 0x26354480U, 0xB562A38FU,
	0xDEB15A49U, 0x25BA1B67U, 0x45EA0E98U, 0x5DFEC0E1U, 0xC32F7502U, 0x814CF012U, 0x8D4697A3U, 0x6BD3F9C6U,
	0x038F5FE7U, 0x15929C95U, 0xBF6D7AEBU, 0x955259DAU, 0xD4BE832DU, 0x587421D3U, 0x49E06929U, 0x8EC9C844U,
	0x75C2896AU, 0xF48E7978U, 0x99583E6BU, 0x27B971DDU, 0xBEE14FB6U, 0xF088AD17U, 0xC920AC66U, 0x7DCE3AB4U,
	0x63DF4A18U, 0xE51A3182U, 0x97513360U, 0x62537F45U, 0xB16477E0U, 0xBB6BAE84U, 0xFE81A01CU, 0xF9082B94U,
	0x70486858U, 0x8F45FD19U, 0x94DE6C87U, 0x527BF8B7U, 0xAB73D323U, 0x724B02E2U, 0xE31F8F57U, 0x6655AB2AU,
	0xB2EB2807U, 0x2FB5C203U, 0x86C57B9AU, 0xD33708A5U, 0x302887F2U, 0x23BFA5B2U, 0x02036ABAU, 0xED16825CU,
	0x8ACF1C2BU, 0xA779B492U, 0xF307F2F0U, 0x4E69E2A1U, 0x65DAF4CDU, 0x0605BED5U, 0xD134621FU, 0xC4A6FE8AU,
	0x342E539DU, 0xA2F355A0U, 0x058AE132U, 0xA4F6EB75U, 0x0B83EC39U, 0x4060EFAAU, 0x5E719F06U, 0xBD6E1051U,
	0x3E218AF9U, 0x96DD063DU, 0xDD3E05AEU, 0x4DE6BD46U, 0x91548DB5U, 0x71C45D05U, 0x0406D46FU, 0x605015FFU,
	0x1998FB24U, 0xD6BDE997U, 0x894043CCU, 0x67D99E77U, 0xB0E842BDU, 0x07898B88U, 0xE7195B38U, 0x79C8EEDBU,
	0xA17C0A47U, 0x7C420FE9U, 0xF8841EC9U, 0x00000000U, 0x09808683U, 0x322BED48U, 0x1E1170ACU, 0x6C5A724EU,
	0xFD0EFFFBU, 0x0F853856U, 0x3DAED51EU, 0x362D3927U, 0x0A0FD964U, 0x685CA621U, 0x9B5B54D1U, 0x24362E3AU,
	0x0C0A67B1U, 0x9357E70FU, 0xB4EE96D2U, 0x1B9B919EU, 0x80C0C54FU, 0x61DC20A2U, 0x5A774B69U, 0x1C121A16U,
	0xE293BA0AU, 0xC0A02AE5U, 0x3C22E043U, 0x121B171DU, 0x0E090D0BU, 0xF28BC7ADU, 0x2DB6A8B9U, 0x141EA9C8U,
	0x57F11985U, 0xAF75074CU, 0xEE99DDBBU, 0xA37F60FDU, 0xF701269FU, 0x5C72F5BCU, 0x44663BC5U, 0x5BFB7E34U,
	0x8B432976U, 0xCB23C6DCU, 0xB6EDFC68U, 0xB8E4F163U, 0xD731DCCAU, 0x42638510U, 0x13972240U, 0x84C61120U,
	0x854A247DU, 0xD2BB3DF8U, 0xAEF93211U, 0xC729A16DU, 0x1D9E2F4BU, 0xDCB230F3U, 0x0D8652ECU, 0x77C1E3D0U,
	0x2BB3166CU, 0xA970B999U, 0x119448FAU, 0x47E96422U, 0xA8FC8CC4U, 0xA0F03F1AU, 0x567D2CD8U, 0x223390EFU,
	0x87494EC7U, 0xD938D1C1U, 0x8CCAA2FEU, 0x98D40B36U, 0xA6F581CFU, 0xA57ADE28U, 0xDAB78E26U, 0x3FADBFA4U,
	0x2C3A9DE4U, 0x5078920DU, 0x6A5FCC9BU, 0x547E4662U, 0xF68D13C2U, 0x90D8B8E8U, 0x2E39F75EU, 0x82C3AFF5U,
	0x9F5D80BEU, 0x69D0937CU, 0x6FD52DA9U, 0xCF2512B3U, 0xC8AC993BU, 0x10187DA7U, 0xE89C636EU, 0xDB3BBB7BU,
	0xCD267809U, 0x6E5918F4U, 0xEC9AB701U, 0x834F9AA8U, 0xE6956E65U, 0xAAFFE67EU, 0x21BCCF08U, 0xEF15E8E6U,
	0xBAE79BD9U, 0x4A6F36CEU, 0xEA9F09D4U, 0x29B07CD6U, 0x31A4B2AFU, 0x2A3F2331U, 0xC6A59430U, 0x35A266C0U,
	0x744EBC37U, 0xFC82CAA6U, 0xE090D0B0U, 0x33A7D815U, 0xF104984AU, 0x41ECDAF7U, 0x7FCD500EU, 0x1791F62FU,
	0x764DD68DU, 0x43EFB04DU, 0xCCAA4D54U, 0xE49604DFU, 0x9ED1B5E3U, 0x4C6A881BU, 0xC12C1FB8U, 0x4665517FU,
	0x9D5EEA04U, 0x018C355DU, 0xFA877473U, 0xFB0B412EU, 0xB3671D5AU, 0x92DBD252U, 0xE9105633U, 0x6DD64713U,
	0x9AD7618CU, 0x37A10C7AU, 0x59F8148EU, 0xEB133C89U, 0xCEA927EEU, 0xB761C935U, 0xE11CE5EDU, 0x7A47B13CU,
	0x9CD2DF59U, 0x55F2733FU, 0x1814CE79U, 0x73C737BFU, 0x53F7CDEAU, 0x5FFDAA5BU, 0xDF3D6F14U, 0x7844DB86U,
	0xCAAFF381U, 0xB968C43EU, 0x3824342CU, 0xC2A3405FU, 0x161DC372U, 0xBCE2250CU, 0x283C498BU, 0xFF0D9541U,
	0x39A80171U, 0x080CB3DEU, 0xD8B4E49CU, 0x6456C190U, 0x7BCB8461U, 0xD532B670U, 0x486C5C74U, 0xD0B85742U
};

const uint32_t AES::Td1[256] = {
	0x5051F4A7U, 0x537E4165U, 0xC31A17A4U, 0x963A275EU, 0xCB3BAB6BU, 0xF11F9D45U, 0xABACFA58U, 0x934BE303U,
	0x552030FAU, 0xF6AD766DU, 0x9188CC76U, 0x25F5024CU, 0xFC4FE5D7U, 0xD7C52ACBU, 0x80263544U, 0x8FB562A3U,
	0x49DEB15AU, 0x6725BA1BU, 0x9845EA0EU, 0xE15DFEC0U, 0x02C32F75U, 0x12814CF0U, 0xA38D4697U, 0xC66BD3F9U,
	0xE7038F5FU, 0x9515929CU, 0xEBBF6D7AU, 0xDA955259U, 0x2DD4BE83U, 0xD3587421U, 0x2949E069U, 0x448EC9C8U,
	0x6A75C289U, 0x78F48E79U, 0x6B99583EU, 0xDD27B971U, 0xB6BEE14FU, 0x17F088ADU, 0x66C920ACU, 0xB47DCE3AU,
	0x1863DF4AU, 0x82E51A31U, 0x60975133U, 0x4562537FU, 0xE0B16477U, 0x84BB6BAEU, 0x1CFE81A0U, 0x94F9082BU,
	0x58704868U, 0x198F45FDU, 0x8794DE6CU, 0xB7527BF8U, 0x23AB73D3U, 0xE2724B02U, 0x57E31F8FU, 0x2A6655ABU,
	0x07B2EB28U, 0x032FB5C2U, 0x9A86C57BU, 0xA5D33708U, 0xF2302887U, 0xB223BFA5U, 0xBA02036AU, 0x5CED1682U,
	0x2B8ACF1CU, 0x92A779B4U, 0xF0F307F2U, 0xA14E69E2U, 0xCD65DAF4U, 0xD50605BEU, 0x1FD13462U, 0x8AC4A6FEU,
	0x9D342E53U, 0xA0A2F355U, 0x32058AE1U, 0x75A4F6EBU, 0x390B83ECU, 0xAA4060EFU, 0x065E719FU, 0x51BD6E10U,
	0xF93E218AU, 0x3D96DD06U, 0xAEDD3E05U, 0x464DE6BDU, 0xB591548DU, 0x0571C45DU, 0x6F0406D4U, 0xFF605015U,
	0x241998FBU, 0x97D6BDE9U, 0xCC894043U, 0x7767D99EU, 0xBDB0E842U, 0x8807898BU, 0x38E7195BU, 0xDB79C8EEU,
	0x47A17C0AU, 0xE97C420FU, 0xC9F8841EU, 0x00000000U, 0x83098086U, 0x48322BEDU, 0xAC1E1170U, 0x4E6C5A72U,
	0xFBFD0EFFU, 0x560F8538U, 0x1E3DAED5U, 0x27362D39U, 0x640A0FD9U, 0x21685CA6U, 0xD19B5B54U, 0x3A24362EU,
	0xB10C0A67U, 0x0F9357E7U, 0xD2B4EE96U, 0x9E1B9B91U, 0x4F80C0C5U, 0xA261DC20U, 0x695A774BU, 0x161C121AU,
	0x0AE293BAU, 0xE5C0A02AU, 0x433C22E0U, 0x1D121B17U, 0x0B0E090DU, 0xADF28BC7U, 0xB92DB6A8U, 0xC8141EA9U,
	0x8557F119U, 0x4CAF7507U, 0xBBEE99DDU, 0xFDA37F60U, 0x9FF70126U, 0xBC5C72F5U, 0xC544663BU, 0x345BFB7EU,
	0x768B4329U, 0xDCCB23C6U, 0x68B6EDFCU, 0x63B8E4F1U, 0xCAD731DCU, 0x10426385U, 0x40139722U, 0x2084C611U,
	0x7D854A24U, 0xF8D2BB3DU, 0x11AEF932U, 0x6DC729A1U, 0x4B1D9E2FU, 0xF3DCB230U, 0xEC0D8652U, 0xD077C1E3U,
	0x6C2BB316U, 0x99A970B9U, 0xFA119448U, 0x2247E964U, 0xC4A8FC8CU, 0x1AA0F03FU, 0xD8567D2CU, 0xEF223390U,
	0xC787494EU, 0xC1D938D1U, 0xFE8CCAA2U, 0x3698D40BU, 0xCFA6F581U, 0x28A57ADEU, 0x26DAB78EU, 0xA43FADBFU,
	0xE42C3A9DU, 0x0D507892U, 0x9B6A5FCCU, 0x62547E46U, 0xC2F68D13U, 0xE890D8B8U, 0x5E2E39F7U, 0xF582C3AFU,
	0xBE9F5D80U, 0x7C69D093U, 0xA96FD52DU, 0xB3CF2512U, 0x3BC8AC99U, 0xA710187DU, 0x6EE89C63U, 0x7BDB3BBBU,
	0x09CD2678U, 0xF46E5918U, 0x01EC9AB7U, 0xA8834F9AU, 0x65E6956EU, 0x7EAAFFE6U, 0x0821BCCFU, 0xE6EF15E8U,
	0xD9BAE79BU, 0xCE4A6F36U, 0xD4EA9F09U, 0xD629B07CU, 0xAF31A4B2U, 0x312A3F23U, 0x30C6A594U, 0xC035A266U,
	0x37744EBCU, 0xA6FC82CAU, 0xB0E090D0U, 0x1533A7D8U, 0x4AF10498U, 0xF741ECDAU, 0x0E7FCD50U, 0x2F1791F6U,
	0x8D764DD6U, 0x4D43EFB0U, 0x54CCAA4DU, 0xDFE49604U, 0xE39ED1B5U, 0x1B4C6A88U, 0xB8C12C1FU, 0x7F466551U,
	0x049D5EEAU, 0x5D018C35U, 0x73FA8774U, 0x2EFB0B41U, 0x5AB3671DU, 0x5292DBD2U, 0x33E91056U, 0x136DD647U,
	0x8C9AD761U, 0x7A37A10CU, 0x8E59F814U, 0x89EB133CU, 0xEECEA927U, 0x35B761C9U, 0xEDE11CE5U, 0x3C7A47B1U,
	0x599CD2DFU, 0x3F55F273U, 0x791814CEU, 0xBF73C737U, 0xEA53F7CDU, 0x5B5FFDAAU, 0x14DF3D6FU, 0x867844DBU,
	0x81CAAFF3U, 0x3EB968C4U, 0x2C382434U, 0x5FC2A340U, 0x72161DC3U, 0x0CBCE225U, 0x8B283C49U, 0x41FF0D95U,
	0x7139A801U, 0xDE080CB3U, 0x9CD8B4E4U, 0x906456C1U, 0x617BCB84U, 0x70D532B6U, 0x74486C5CU, 0x42D0B857U
};

const uint32_t AES::Td2[256] = {
	0xA75051F4U, 0x65537E41U, 0xA4C31A17U, 0x5E963A27U, 0x6BCB3BABU, 0x45F11F9DU, 0x58ABACFAU, 0x03934BE3U,
	0xFA552030U, 0x6DF6AD76U, 0x769188CCU, 0x4C25F502U, 0xD7FC4FE5U, 0xCBD7C52AU, 0x44802635U, 0xA38FB562U,
	0x5A49DEB1U, 0x1B6725BAU, 0x0E9845EAU, 0xC0E15DFEU, 0x7502C32FU, 0xF012814CU, 0x97A38D46U, 0xF9C66BD3U,
	0x5FE7038FU, 0x9C951592U, 0x7AEBBF6DU, 0x59DA9552U, 0x832DD4BEU, 0x21D35874U, 0x692949E0U, 0xC8448EC9U,
	0x896A75C2U, 0x7978F48EU, 0x3E6B9958U, 0x71DD27B9U, 0x4FB6BEE1U, 0xAD17F088U, 0xAC66C920U, 0x3AB47DCEU,
	0x4A1863DFU, 0x3182E51AU, 0x33609751U, 0x7F456253U, 0x77E0B164U, 0xAE84BB6BU, 0xA01CFE81U, 0x2B94F908U,
	0x68587048U, 0xFD198F45U, 0x6C8794DEU, 0xF8B7527BU, 0xD323AB73U, 0x02E2724BU, 0x8F57E31FU, 0xAB2A6655U,
	0x2807B2EBU, 0xC2032FB5U, 0x7B9A86C5U, 0x08A5D337U, 0x87F23028U, 0xA5B223BFU, 0x6ABA0203U, 0x825CED16U,
	0x1C2B8ACFU, 0xB492A779U, 0xF2F0F307U, 0xE2A14E69U, 0xF4CD65DAU, 0xBED50605U, 0x621FD134U, 0xFE8AC4A6U,
	0x539D342EU, 0x55A0A2F3U, 0xE132058AU, 0xEB75A4F6U, 0xEC390B83U, 0xEFAA4060U, 0x9F065E71U, 0x1051BD6EU,
	0x8AF93E21U, 0x063D96DDU, 0x05AEDD3EU, 0xBD464DE6U, 0x8DB59154U, 0x5D0571C4U, 0xD46F0406U, 0x15FF6050U,
	0xFB241998U, 0xE997D6BDU, 0x43CC8940U, 0x9E7767D9U, 0x42BDB0E8U, 0x8B880789U, 0x5B38E719U, 0xEEDB79C8U,
	0x0A47A17CU, 0x0FE97C42U, 0x1EC9F884U, 0x00000000U, 0x86830980U, 0xED48322BU, 0x70AC1E11U, 0x724E6C5AU,
	0xFFFBFD0EU, 0x38560F85U, 0xD51E3DAEU, 0x3927362DU, 0xD9640A0FU, 0xA621685CU, 0x54D19B5BU, 0x2E3A2436U,
	0x67B10C0AU, 0xE70F9357U, 0x96D2B4EEU, 0x919E1B9BU, 0xC54F80C0U, 0x20A261DCU, 0x4B695A77U, 0x1A161C12U,
	0xBA0AE293U, 0x2AE5C0A0U, 0xE0433C22U, 0x171D121BU, 0x0D0B0E09U, 0xC7ADF28BU, 0xA8B92DB6U, 0xA9C8141EU,
	0x198557F1U, 0x074CAF75U, 0xDDBBEE99U, 0x60FDA37FU, 0x269FF701U, 0xF5BC5C72U, 0x3BC54466U, 0x7E345BFBU,
	0x29768B43U, 0xC6DCCB23U, 0xFC68B6EDU, 0xF163B8E4U, 0xDCCAD731U, 0x85104263U, 0x22401397U, 0x112084C6U,
	0x247D854AU, 0x3DF8D2BBU, 0x3211AEF9U, 0xA16DC729U, 0x2F4B1D9EU, 0x30F3DCB2U, 0x52EC0D86U, 0xE3D077C1U,
	0x166C2BB3U, 0xB999A970U, 0x48FA1194U, 0x642247E9U, 0x8CC4A8FCU, 0x3F1AA0F0U, 0x2CD8567DU, 0x90EF2233U,
	0x4EC78749U, 0xD1C1D938U, 0xA2FE8CCAU, 0x0B3698D4U, 0x81CFA6F5U, 0xDE28A57AU, 0x8E26DAB7U, 0xBFA43FADU,
	0x9DE42C3AU, 0x920D5078U, 0xCC9B6A5FU, 0x4662547EU, 0x13C2F68DU, 0xB8E890D8U, 0xF75E2E39U, 0xAFF582C3U,
	0x80BE9F5DU, 0x937C69D0U, 0x2DA96FD5U, 0x12B3CF25U, 0x993BC8ACU, 0x7DA71018U, 0x636EE89CU, 0xBB7BDB3BU,
	0x7809CD26U, 0x18F46E59U, 0xB701EC9AU, 0x9AA8834FU, 0x6E65E695U, 0xE67EAAFFU, 0xCF0821BCU, 0xE8E6EF15U,
	0x9BD9BAE7U, 0x36CE4A6FU, 0x09D4EA9FU, 0x7CD629B0U, 0xB2AF31A4U, 0x23312A3FU, 0x9430C6A5U, 0x66C035A2U,
	0xBC37744EU, 0xCAA6FC82U, 0xD0B0E090U, 0xD81533A7U, 0x984AF104U, 0xDAF741ECU, 0x500E7FCDU, 0xF62F1791U,
	0xD68D764DU, 0xB04D43EFU, 0x4D54CCAAU, 0x04DFE496U, 0xB5E39ED1U, 0x881B4C6AU, 0x1FB8C12CU, 0x517F4665U,
	0xEA049D5EU, 0x355D018CU, 0x7473FA87U, 0x412EFB0BU, 0x1D5AB367U, 0xD25292DBU, 0x5633E910U, 0x47136DD6U,
	0x618C9AD7U, 0x0C7A37A1U, 0x148E59F8U, 0x3C89EB13U, 0x27EECEA9U, 0xC935B761U, 0xE5EDE11CU, 0xB13C7A47U,
	0xDF599CD2U, 0x733F55F2U, 0xCE791814U, 0x37BF73C7U, 0xCDEA53F7U, 0xAA5B5FFDU, 0x6F14DF3DU, 0xDB867844U,
	0xF381CAAFU, 0xC43EB968U, 0x342C3824U, 0x405FC2A3U, 0xC372161DU, 0x250CBCE2U, 0x498B283CU, 0x9541FF0DU,
	0x017139A8U, 0xB3DE080CU, 0xE49CD8B4U, 0xC1906456U, 0x84617BCBU, 0xB670D532U, 0x5C74486CU, 0x5742D0B8U
};

const uint32_t AES::Td3[256] = {
	0xF4A75051U, 0x4165537EU, 0x17A4C31AU, 0x275E963AU, 0xAB6BCB3BU, 0x9D45F11FU, 0xFA58ABACU, 0xE303934BU,
	0x30FA5520U, 0x766DF6ADU, 0xCC769188U, 0x024C25F5U, 0xE5D7FC4FU, 0x2ACBD7C5U, 0x35448026U, 0x62A38FB5U,
	0xB15A49DEU, 0xBA1B6725U, 0xEA0E9845U, 0xFEC0E15DU, 0x2F7502C3U, 0x4CF01281U, 0x4697A38DU, 0xD3F9C66BU,
	0x8F5FE703U, 0x929C9515U, 0x6D7AEBBFU, 0x5259DA95U, 0xBE832DD4U, 0x7421D358U, 0xE0692949U, 0xC9C8448EU,
	0xC2896A75U, 0x8E7978F4U, 0x583E6B99U, 0xB971DD27U, 0xE14FB6BEU, 0x88AD17F0U, 0x20AC66C9U, 0xCE3AB47DU,
	0xDF4A1863U, 0x1A3182E5U, 0x51336097U, 0x537F4562U, 0x6477E0B1U, 0x6BAE84BBU, 0x81A01CFEU, 0x082B94F9U,
	0x48685870U, 0x45FD198FU, 0xDE6C8794U, 0x7BF8B752U, 0x73D323ABU, 0x4B02E272U, 0x1F8F57E3U, 0x55AB2A66U,
	0xEB2807B2U, 0xB5C2032FU, 0xC57B9A86U, 0x3708A5D3U, 0x2887F230U, 0xBFA5B223U, 0x036ABA02U, 0x16825CEDU,
	0xCF1C2B8AU, 0x79B492A7U, 0x07F2F0F3U, 0x69E2A14EU, 0xDAF4CD65U, 0x05BED506U, 0x34621FD1U, 0xA6FE8AC4U,
	0x2E539D34U, 0xF355A0A2U, 0x8AE13205U, 0xF6EB75A4U, 0x83EC390BU, 0x60EFAA40U, 0x719F065EU, 0x6E1051BDU,
	0x218AF93EU, 0xDD063D96U, 0x3E05AEDDU, 0xE6BD464DU, 0x548DB591U, 0xC45D0571U, 0x06D46F04U, 0x5015FF60U,
	0x98FB2419U, 0xBDE997D6U, 0x4043CC89U, 0xD99E7767U, 0xE842BDB0U, 0x898B8807U, 0x195B38E7U, 0xC8EEDB79U,
	0x7C0A47A1U, 0x420FE97CU, 0x841EC9F8U, 0x00000000U, 0x80868309U, 0x2BED4832U, 0x1170AC1EU, 0x5A724E6CU,
	0x0EFFFBFDU, 0x8538560FU, 0xAED51E3DU, 0x2D392736U, 0x0FD9640AU, 0x5CA62168U, 0x5B54D19BU, 0x362E3A24U,
	0x0A67B10CU, 0x57E70F93U, 0xEE96D2B4U, 0x9B919E1BU, 0xC0C54F80U, 0xDC20A261U, 0x774B695AU, 0x121A161CU,
	0x93BA0AE2U, 0xA02AE5C0U, 0x22E0433CU, 0x1B171D12U, 0x090D0B0EU, 0x8BC7ADF2U, 0xB6A8B92DU, 0x1EA9C814U,
	0xF1198557U, 0x75074CAFU, 0x99DDBBEEU, 0x7F60FDA3U, 0x01269FF7U, 0x72F5BC5CU, 0x663BC544U, 0xFB7E345BU,
	0x4329768BU, 0x23C6DCCBU, 0xEDFC68B6U, 0xE4F163B8U, 0x31DCCAD7U, 0x63851042U, 0x97224013U, 0xC6112084U,
	0x4A247D85U, 0xBB3DF8D2U, 0xF93211AEU, 0x29A16DC7U, 0x9E2F4B1DU, 0xB230F3DCU, 0x8652EC0DU, 0xC1E3D077U,
	0xB3166C2BU, 0x70B999A9U, 0x9448FA11U, 0xE9642247U, 0xFC8CC4A8U, 0xF03F1AA0U, 0x7D2CD856U, 0x3390EF22U,
	0x494EC787U, 0x38D1C1D9U, 0xCAA2FE8CU, 0xD40B3698U, 0xF581CFA6U, 0x7ADE28A5U, 0xB78E26DAU, 0xADBFA43FU,
	0x3A9DE42CU, 0x78920D50U, 0x5FCC9B6AU, 0x7E466254U, 0x8D13C2F6U, 0xD8B8E890U, 0x39F75E2EU, 0xC3AFF582U,
	0x5D80BE9FU, 0xD0937C69U, 0xD52DA96FU, 0x2512B3CFU, 0xAC993BC8U, 0x187DA710U, 0x9C636EE8U, 0x3BBB7BDBU,
	0x267809CDU, 0x5918F46EU, 0x9AB701ECU, 0x4F9AA883U, 0x956E65E6U, 0xFFE67EAAU, 0xBCCF0821U, 0x15E8E6EFU,
	0xE79BD9BAU, 0x6F36CE4AU, 0x9F09D4EAU, 0xB07CD629U, 0xA4B2AF31U, 0x3F23312AU, 0xA59430C6U, 0xA266C035U,
	0x4EBC3774U, 0x82CAA6FCU, 0x90D0B0E0U, 0xA7D81533U, 0x04984AF1U, 0xECDAF741U, 0xCD500E7FU, 0x91F62F17U,
	0x4DD68D76U, 0xEFB04D43U, 0xAA4D54CCU, 0x9604DFE4U, 0xD1B5E39EU, 0x6A881B4CU, 0x2C1FB8C1U, 0x65517F46U,
	0x5EEA049DU, 0x8C355D01U, 0x877473FAU, 0x0B412EFBU, 0x671D5AB3U, 0xDBD25292U, 0x105633E9U, 0xD647136DU,
	0xD7618C9AU, 0xA10C7A37U, 0xF8148E59U, 0x133C89EBU, 0xA927EECEU, 0x61C935B7U, 0x1CE5EDE1U, 0x47B13C7AU,
	0xD2DF599CU, 0xF2733F55U, 0x14CE7918U, 0xC737BF73U, 0xF7CDEA53U, 0xFDAA5B5FU, 0x3D6F14DFU, 0x44DB8678U,
	0xAFF381CAU, 0x68C43EB9U, 0x24342C38U, 0xA3405FC2U, 0x1DC37216U, 0xE2250CBCU, 0x3C498B28U, 0x0D9541FFU,
	0xA8017139U, 0x0CB3DE08U, 0xB4E49CD8U, 0x56C19064U, 0xCB84617BU, 0x32B670D5U, 0x6C5C7448U, 0xB85742D0U
};

const uint32_t AES::Td4[256] = {
	0x52525252U, 0x09090909U, 0x6A6A6A6AU, 0xD5D5D5D5U, 0x30303030U, 0x36363636U, 0xA5A5A5A5U, 0x38383838U,
	0xBFBFBFBFU, 0x40404040U, 0xA3A3A3A3U, 0x9E9E9E9EU, 0x81818181U, 0xF3F3F3F3U, 0xD7D7D7D7U, 0xFBFBFBFBU,
	0x7C7C7C7CU, 0xE3E3E3E3U, 0x39393939U, 0x82828282U, 0x9B9B9B9BU, 0x2F2F2F2FU, 0xFFFFFFFFU, 0x87878787U,
	0x34343434U, 0x8E8E8E8EU, 0x43434343U, 0x44444444U, 0xC4C4C4C4U, 0xDEDEDEDEU, 0xE9E9E9E9U, 0xCBCBCBCBU,
	0x54545454U, 0x7B7B7B7BU, 0x94949494U, 0x32323232U, 0xA6A6A6A6U, 0xC2C2C2C2U, 0x23232323U, 0x3D3D3D3DU,
	0xEEEEEEEEU, 0x4C4C4C4CU, 0x95959595U, 0x0B0B0B0BU, 0x42424242U, 0xFAFAFAFAU, 0xC3C3C3C3U, 0x4E4E4E4EU,
	0x08080808U, 0x2E2E2E2EU, 0xA1A1A1A1U, 0x66666666U, 0x28282828U, 0xD9D9D9D9U, 0x24242424U, 0xB2B2B2B2U,
	0x76767676U, 0x5B5B5B5BU, 0xA2A2A2A2U, 0x49494949U, 0x6D6D6D6DU, 0x8B8B8B8BU, 0xD1D1D1D1U, 0x25252525U,
	0x72727272U, 0xF8F8F8F8U, 0xF6F6F6F6U, 0x64646464U, 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
	0xD4D4D4D4U, 0xA4A4A4A4U, 0x5C5C5C5CU, 0xCCCCCCCCU, 0x5D5D5D5DU, 0x65656565U, 0xB6B6B6B6U, 0x92929292U,
	0x6C6C6C6CU, 0x70707070U, 0x48484848U, 0x50505050U, 0xFDFDFDFDU, 0xEDEDEDEDU, 0xB9B9B9B9U, 0xDADADADAU,
	0x5E5E5E5EU, 0x15151515U, 0x46464646U, 0x57575757U, 0xA7A7A7A7U, 0x8D8D8D8DU, 0x9D9D9D9DU, 0x84848484U,
	0x90909090U, 0xD8D8D8D8U, 0xABABABABU, 0x00000000U, 0x8C8C8C8CU, 0xBCBCBCBCU, 0xD3D3D3D3U, 0x0A0A0A0AU,
	0xF7F7F7F7U, 0xE4E4E4E4U, 0x58585858U, 0x05050505U, 0xB8B8B8B8U, 0xB3B3B3B3U, 0x45454545U, 0x06060606U,
	0xD0D0D0D0U, 0x2C2C2C2CU, 0x1E1E1E1EU, 0x8F8F8F8FU, 0xCACACACAU, 0x3F3F3F3FU, 0x0F0F0F0FU, 0x02020202U,
	0xC1C1C1C1U, 0xAFAFAFAFU, 0xBDBDBDBDU, 0x03030303U, 0x01010101U, 0x13131313U, 0x8A8A8A8AU, 0x6B6B6B6BU,
	0x3A3A3A3AU, 0x91919191U, 0x11111111U, 0x41414141U, 0x4F4F4F4FU, 0x67676767U, 0xDCDCDCDCU, 0xEAEAEAEAU,
	0x97979797U, 0xF2F2F2F2U, 0xCFCFCFCFU, 0xCECECECEU, 0xF0F0F0F0U, 0xB4B4B4B4U, 0xE6E6E6E6U, 0x73737373U,
	0x96969696U, 0xACACACACU, 0x74747474U, 0x22222222U, 0xE7E7E7E7U, 0xADADADADU, 0x35353535U, 0x85858585U,
	0xE2E2E2E2U, 0xF9F9F9F9U, 0x37373737U, 0xE8E8E8E8U, 0x1C1C1C1CU, 0x75757575U, 0xDFDFDFDFU, 0x6E6E6E6EU,
	0x47474747U, 0xF1F1F1F1U, 0x1A1A1A1AU, 0x71717171U, 0x1D1D1D1DU, 0x29292929U, 0xC5C5C5C5U, 0x89898989U,
	0x6F6F6F6FU, 0xB7B7B7B7U, 0x62626262U, 0x0E0E0E0EU, 0xAAAAAAAAU, 0x18181818U, 0xBEBEBEBEU, 0x1B1B1B1BU,
	0xFCFCFCFCU, 0x56565656U, 0x3E3E3E3EU, 0x4B4B4B4BU, 0xC6C6C6C6U, 0xD2D2D2D2U, 0x79797979U, 0x20202020U,
	0x9A9A9A9AU, 0xDBDBDBDBU, 0xC0C0C0C0U, 0xFEFEFEFEU, 0x78787878U, 0xCDCDCDCDU, 0x5A5A5A5AU, 0xF4F4F4F4U,
	0x1F1F1F1FU, 0xDDDDDDDDU, 0xA8A8A8A8U, 0x33333333U, 0x88888888U, 0x07070707U, 0xC7C7C7C7U, 0x31313131U,
	0xB1B1B1B1U, 0x12121212U, 0x10101010U, 0x59595959U, 0x27272727U, 0x80808080U, 0xECECECECU, 0x5F5F5F5FU,
	0x60606060U, 0x51515151U, 0x7F7F7F7FU, 0xA9A9A9A9U, 0x19191919U, 0xB5B5B5B5U, 0x4A4A4A4AU, 0x0D0D0D0DU,
	0x2D2D2D2DU, 0xE5E5E5E5U, 0x7A7A7A7AU, 0x9F9F9F9FU, 0x93939393U, 0xC9C9C9C9U, 0x9C9C9C9CU, 0xEFEFEFEFU,
	0xA0A0A0A0U, 0xE0E0E0E0U, 0x3B3B3B3BU, 0x4D4D4D4DU, 0xAEAEAEAEU, 0x2A2A2A2AU, 0xF5F5F5F5U, 0xB0B0B0B0U,
	0xC8C8C8C8U, 0xEBEBEBEBU, 0xBBBBBBBBU, 0x3C3C3C3CU, 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
	0x17171717U, 0x2B2B2B2BU, 0x04040404U, 0x7E7E7E7EU, 0xBABABABAU, 0x77777777U, 0xD6D6D6D6U, 0x26262626U,
	0xE1E1E1E1U, 0x69696969U, 0x14141414U, 0x63636363U, 0x55555555U, 0x21212121U, 0x0C0C0C0CU, 0x7D7D7D7DU
};

const uint32_t AES::rcon[11] = {
	0x00000000U, 0x01000000U, 0x02000000U, 0x04000000U, 0x08000000U, 0x10000000U, 0x20000000U, 0x40000000U,
	0x80000000U, 0x1B000000U, 0x36000000U
};

AES::AES()
{
	Nb = 4;
	Nk = 4;
	Nr = 10;

	std::fill_n(_iv, 16, 0);
	std::fill_n(_erk, 60, 0);
	std::fill_n(_drk, 60, 0);

	_tp = 0;
}

AES::~AES()
{
	CleanUp();
}

void AES::CleanUp()
{
	std::fill_n(_iv, 16, 0);
	std::fill_n(_erk, 60, 0);
	std::fill_n(_drk, 60, 0);
	_tp = 0;
}

void AES::SetKey(const uint8_t *key, Mode mode)
{
	int i;
	uint32_t tmp;
	int ks_sz;

	switch (mode) {
		case AES_128: Nk = 4; Nr = 10; break;
		case AES_192: Nk = 6; Nr = 12; break;
		case AES_256: Nk = 8; Nr = 14; break;
	}

	ks_sz = Nb * (Nr + 1);

	for (i = 0; i < Nk; i++) {
		_erk[i] = (key[4*i] << 24) | (key[4*i+1] << 16) | (key[4*i+2] << 8) | key[4*i+3];
	}

	for (; i < ks_sz; i++) {
		tmp = _erk[i-1];
		if (i % Nk == 0) {
			tmp = (Te4[(tmp >> 16) & 0xFF] & 0xFF000000) ^ (Te4[(tmp >> 8) & 0xFF] & 0xFF0000) ^ (Te4[tmp & 0xFF] & 0xFF00) ^ (Te4[(tmp >> 24) & 0xFF] & 0xFF) ^ rcon[i / Nk];
		} else if ((Nk > 6) && ((i % Nk) == 4)) {
			tmp = (Te4[(tmp >> 24) & 0xFF] & 0xFF000000) ^ (Te4[(tmp >> 16) & 0xFF] & 0xFF0000) ^ (Te4[(tmp >> 8) & 0xFF] & 0xFF00) ^ (Te4[tmp & 0xFF] & 0xFF);
		}
		_erk[i] = _erk[i-Nk] ^ tmp;
	}

	for (i = 0; i < ks_sz; i += 4) {
		_drk[i    ] = _erk[ks_sz - i - 4];
		_drk[i + 1] = _erk[ks_sz - i - 3];
		_drk[i + 2] = _erk[ks_sz - i - 2];
		_drk[i + 3] = _erk[ks_sz - i - 1];
	}

	for (i = 4; i < (ks_sz - 4); i++) {
		_drk[i] = Td0[Te4[(_drk[i] >> 24)] & 0xFF] ^ Td1[Te4[(_drk[i] >> 16) & 0xFF] & 0xFF] ^ Td2[Te4[(_drk[i] >> 8) & 0xFF] & 0xFF] ^ Td3[Te4[_drk[i] & 0xFF] & 0xFF];
	}

	SetIV(0);
}

void AES::Encrypt(const uint8_t *src, uint8_t *dst)
{
	uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
	int r, ki;

	s0 = (src[0] << 24 | src[1] << 16 | src[2] << 8 | src[3]) ^ _erk[0];
	s1 = (src[4] << 24 | src[5] << 16 | src[6] << 8 | src[7]) ^ _erk[1];
	s2 = (src[8] << 24 | src[9] << 16 | src[10] << 8 | src[11]) ^ _erk[2];
	s3 = (src[12] << 24 | src[13] << 16 | src[14] << 8 | src[15]) ^ _erk[3];

	ki = 4;
	r = Nr >> 1;

	for (;;) {
		t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xFF] ^ Te2[(s2 >> 8) & 0xFF] ^ Te3[s3 & 0xFF] ^ _erk[ki++];
		t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xFF] ^ Te2[(s3 >> 8) & 0xFF] ^ Te3[s0 & 0xFF] ^ _erk[ki++];
		t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xFF] ^ Te2[(s0 >> 8) & 0xFF] ^ Te3[s1 & 0xFF] ^ _erk[ki++];
		t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xFF] ^ Te2[(s1 >> 8) & 0xFF] ^ Te3[s2 & 0xFF] ^ _erk[ki++];
		if (--r == 0) break;
		s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xFF] ^ Te2[(t2 >> 8) & 0xFF] ^ Te3[t3 & 0xFF] ^ _erk[ki++];
		s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xFF] ^ Te2[(t3 >> 8) & 0xFF] ^ Te3[t0 & 0xFF] ^ _erk[ki++];
		s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xFF] ^ Te2[(t0 >> 8) & 0xFF] ^ Te3[t1 & 0xFF] ^ _erk[ki++];
		s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xFF] ^ Te2[(t1 >> 8) & 0xFF] ^ Te3[t2 & 0xFF] ^ _erk[ki++];
	}

	s0 = (Te4[t0 >> 24] & 0xFF000000) ^ (Te4[(t1 >> 16) & 0xFF] & 0xFF0000) ^ (Te4[(t2 >> 8) & 0xFF] & 0xFF00) ^ (Te4[t3 & 0xFF] & 0xFF) ^ _erk[ki++];
	s1 = (Te4[t1 >> 24] & 0xFF000000) ^ (Te4[(t2 >> 16) & 0xFF] & 0xFF0000) ^ (Te4[(t3 >> 8) & 0xFF] & 0xFF00) ^ (Te4[t0 & 0xFF] & 0xFF) ^ _erk[ki++];
	s2 = (Te4[t2 >> 24] & 0xFF000000) ^ (Te4[(t3 >> 16) & 0xFF] & 0xFF0000) ^ (Te4[(t0 >> 8) & 0xFF] & 0xFF00) ^ (Te4[t1 & 0xFF] & 0xFF) ^ _erk[ki++];
	s3 = (Te4[t3 >> 24] & 0xFF000000) ^ (Te4[(t0 >> 16) & 0xFF] & 0xFF0000) ^ (Te4[(t1 >> 8) & 0xFF] & 0xFF00) ^ (Te4[t2 & 0xFF] & 0xFF) ^ _erk[ki++];

	dst[0] = s0 >> 24; dst[1] = s0 >> 16; dst[2] = s0 >> 8; dst[3] = s0;
	dst[4] = s1 >> 24; dst[5] = s1 >> 16; dst[6] = s1 >> 8; dst[7] = s1;
	dst[8] = s2 >> 24; dst[9] = s2 >> 16; dst[10] = s2 >> 8; dst[11] = s2;
	dst[12] = s3 >> 24; dst[13] = s3 >> 16; dst[14] = s3 >> 8; dst[15] = s3;
}

void AES::Decrypt(const uint8_t *src, uint8_t *dst)
{
	uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
	int r, ki;

	s0 = (src[0] << 24 | src[1] << 16 | src[2] << 8 | src[3]) ^ _drk[0];
	s1 = (src[4] << 24 | src[5] << 16 | src[6] << 8 | src[7]) ^ _drk[1];
	s2 = (src[8] << 24 | src[9] << 16 | src[10] << 8 | src[11]) ^ _drk[2];
	s3 = (src[12] << 24 | src[13] << 16 | src[14] << 8 | src[15]) ^ _drk[3];

	ki = 4;
	r = Nr >> 1;

	for (;;) {
		t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xFF] ^ Td2[(s2 >> 8) & 0xFF] ^ Td3[s1 & 0xFF] ^ _drk[ki++];
		t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xFF] ^ Td2[(s3 >> 8) & 0xFF] ^ Td3[s2 & 0xFF] ^ _drk[ki++];
		t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xFF] ^ Td2[(s0 >> 8) & 0xFF] ^ Td3[s3 & 0xFF] ^ _drk[ki++];
		t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xFF] ^ Td2[(s1 >> 8) & 0xFF] ^ Td3[s0 & 0xFF] ^ _drk[ki++];
		if (--r == 0) break;
		s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xFF] ^ Td2[(t2 >> 8) & 0xFF] ^ Td3[t1 & 0xFF] ^ _drk[ki++];
		s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xFF] ^ Td2[(t3 >> 8) & 0xFF] ^ Td3[t2 & 0xFF] ^ _drk[ki++];
		s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xFF] ^ Td2[(t0 >> 8) & 0xFF] ^ Td3[t3 & 0xFF] ^ _drk[ki++];
		s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xFF] ^ Td2[(t1 >> 8) & 0xFF] ^ Td3[t0 & 0xFF] ^ _drk[ki++];
	}

	s0 = (Td4[t0 >> 24] & 0xFF000000) ^ (Td4[(t3 >> 16) & 0xFF] & 0xFF0000) ^ (Td4[(t2 >> 8) & 0xFF] & 0xFF00) ^ (Td4[t1 & 0xFF] & 0xFF) ^ _drk[ki++];
	s1 = (Td4[t1 >> 24] & 0xFF000000) ^ (Td4[(t0 >> 16) & 0xFF] & 0xFF0000) ^ (Td4[(t3 >> 8) & 0xFF] & 0xFF00) ^ (Td4[t2 & 0xFF] & 0xFF) ^ _drk[ki++];
	s2 = (Td4[t2 >> 24] & 0xFF000000) ^ (Td4[(t1 >> 16) & 0xFF] & 0xFF0000) ^ (Td4[(t0 >> 8) & 0xFF] & 0xFF00) ^ (Td4[t3 & 0xFF] & 0xFF) ^ _drk[ki++];
	s3 = (Td4[t3 >> 24] & 0xFF000000) ^ (Td4[(t2 >> 16) & 0xFF] & 0xFF0000) ^ (Td4[(t1 >> 8) & 0xFF] & 0xFF00) ^ (Td4[t0 & 0xFF] & 0xFF) ^ _drk[ki++];

	dst[0] = s0 >> 24; dst[1] = s0 >> 16; dst[2] = s0 >> 8; dst[3] = s0;
	dst[4] = s1 >> 24; dst[5] = s1 >> 16; dst[6] = s1 >> 8; dst[7] = s1;
	dst[8] = s2 >> 24; dst[9] = s2 >> 16; dst[10] = s2 >> 8; dst[11] = s2;
	dst[12] = s3 >> 24; dst[13] = s3 >> 16; dst[14] = s3 >> 8; dst[15] = s3;
}

void AES::SetIV(const uint8_t *iv)
{
	size_t j;

	_tp = 0;

	if (iv == 0)
		iv = zeros;

	for (j = 0; j < 16; j++) _iv[j] = iv[j];
}

void AES::EncryptCBC(const uint8_t *src, uint8_t *dst, size_t size)
{
	size_t i, j;
	uint8_t tmp[16];

	for (i = 0; i < size; i += 16) {
		for (j = 0; j < 16; j++) tmp[j] = src[i+j] ^ _iv[j];
		Encrypt(tmp, &dst[i]);
		for (j = 0; j < 16; j++) _iv[j] = dst[i+j];
	}
}

void AES::DecryptCBC(const uint8_t *src, uint8_t *dst, size_t size)
{
	size_t i, j;
	uint8_t tmp[16];

	for (i = 0; i < size; i += 16) {
		for (j = 0; j < 16; j++) tmp[j] = src[i+j];
		Decrypt(&src[i], &dst[i]);
		for (j = 0; j < 16; j++) {
			dst[i+j] ^= _iv[j];
			_iv[j] = tmp[j];
		}
	}
}

void AES::EncryptCFB(const uint8_t *src, uint8_t *dst, size_t size)
{
	size_t i;

	for (i = 0; i < size; i++, _tp = (_tp + 1) & 15) {
		if (_tp == 0)
			Encrypt(_iv, _iv);
		dst[i] = src[i] ^ _iv[_tp];
		_iv[_tp] = dst[i];
	}
}

void AES::DecryptCFB(const uint8_t *src, uint8_t *dst, size_t size)
{
	size_t i;
	uint8_t t;

	for (i = 0; i < size; i++, _tp = (_tp + 1) & 15) {
		if (_tp == 0)
			Encrypt(_iv, _iv);
		t = src[i];
		dst[i] = src[i] ^ _iv[_tp];
		_iv[_tp] = t;
	}
}

void AES::CryptOFB(const uint8_t *src, uint8_t *dst, size_t size)
{
	size_t i;

	for (i = 0; i < size; i++, _tp = (_tp + 1) & 15) {
		if (_tp == 0)
			Encrypt(_iv, _iv);
		dst[i] = src[i] ^ _iv[_tp];
	}
}

const uint8_t AES::zeros[32] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
